package yw.nmh.service.impl;

import cn.dev33.satoken.secure.BCrypt;
import cn.dev33.satoken.stp.StpUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import yw.nmh.AccountInfo.domain.AccountInfo;
import yw.nmh.AccountInfo.dto.LoginDTO;
import yw.nmh.AccountInfo.vo.AccountInfoVO;
import yw.nmh.exception.BusinessException;
import yw.nmh.mapper.AccountInfoMapper;
import yw.nmh.result.PageDTO;
import yw.nmh.service.AccountInfoService;
import java.time.LocalDateTime;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author sun
 * @description 针对表【account_info(人员管理表)】的数据库操作Service实现
 * @createDate 2024-12-26 13:58:42
 */
@Service
public class AccountInfoServiceImpl extends ServiceImpl<AccountInfoMapper, AccountInfo>
        implements AccountInfoService {

    @Resource
    private AccountInfoMapper accountInfoMapper;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void save(AccountInfoVO accountInfoVO) {
        // 检查手机号是否已存在
        checkPhoneExists(accountInfoVO.getAccPhone(), null);

        AccountInfo accountInfo = new AccountInfo();
        accountInfo.setAccName(accountInfoVO.getAccName());
        accountInfo.setAccPhone(accountInfoVO.getAccPhone());
        accountInfo.setIsEnable(1); // 默认启用
        accountInfo.setCreateTime(LocalDateTime.now());
        accountInfo.setUpdateTime(LocalDateTime.now());

        // 生成账号
        accountInfo.setAccount(generateAccount());

        // 设置默认密码（手机号后6位）
        String defaultPassword = accountInfoVO.getAccPhone().substring(5);
        accountInfo.setPassword(BCrypt.hashpw(defaultPassword));

        save(accountInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void update(AccountInfoVO accountInfoVO) {
        // 获取原有用户信息
        AccountInfo oldAccountInfo = getById(accountInfoVO.getId());
        if (oldAccountInfo == null) {
            throw new BusinessException("用户不存在");
        }

        // 如果传入了手机号且与原手机号不同，才进行手机号唯一性检查
        if (accountInfoVO.getAccPhone() != null && !accountInfoVO.getAccPhone().equals(oldAccountInfo.getAccPhone())) {
            checkPhoneExists(accountInfoVO.getAccPhone(), accountInfoVO.getId());
            oldAccountInfo.setAccPhone(accountInfoVO.getAccPhone());
        }

        // 如果传入了姓名，则更新姓名
        if (accountInfoVO.getAccName() != null) {
            oldAccountInfo.setAccName(accountInfoVO.getAccName());
        }

        oldAccountInfo.setUpdateTime(LocalDateTime.now());
        updateById(oldAccountInfo);
    }

    @Override
    public String generateAccount() {
        // 获取最大的账号序号
        LambdaQueryWrapper<AccountInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.orderByDesc(AccountInfo::getAccount);
        wrapper.last("LIMIT 1");

        AccountInfo lastAccount = getOne(wrapper);

        int nextNumber;
        if (lastAccount == null || !lastAccount.getAccount().startsWith("YZ")) {
            nextNumber = 1;
        } else {
            String currentNumber = lastAccount.getAccount().substring(2);
            nextNumber = Integer.parseInt(currentNumber) + 1;
        }

        return String.format("YZ%04d", nextNumber);
    }

    private void checkPhoneExists(String phone, Integer excludeId) {
        LambdaQueryWrapper<AccountInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountInfo::getAccPhone, phone);
        if (excludeId != null) {
            wrapper.ne(AccountInfo::getId, excludeId);
        }
        if (count(wrapper) > 0) {
            throw new BusinessException("手机号已存在");
        }
    }

    @Override
    public Boolean login(LoginDTO loginDto) {
        LambdaQueryWrapper<AccountInfo> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AccountInfo::getAccount, loginDto.getAccount());
        AccountInfo accountInfo = getOne(wrapper);
        if (accountInfo == null) {
            return false;
        }
        if (BCrypt.checkpw(loginDto.getPassword(), accountInfo.getPassword())){
            StpUtil.login(loginDto.getAccount());
            return true;
        }
        return false;
    }

    @Override
    public Page<AccountInfoVO> getAccount(PageDTO pageDTO) {
        Page<AccountInfo> page = new Page<>(pageDTO.getPageNumber(), pageDTO.getPageSize());

        LambdaQueryWrapper<AccountInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(AccountInfo::getCreateTime);

        Page<AccountInfo> accountInfoPage = this.page(page, queryWrapper);

        Page<AccountInfoVO> resultPage = new Page<>();
        resultPage.setRecords(convertToVOList(accountInfoPage.getRecords()));
        resultPage.setTotal(accountInfoPage.getTotal());
        resultPage.setCurrent(accountInfoPage.getCurrent());
        resultPage.setSize(accountInfoPage.getSize());

        return resultPage;
    }

    private List<AccountInfoVO> convertToVOList(List<AccountInfo> accountInfoList) {
        return accountInfoList.stream()
                .map(this::convertToVO)
                .collect(Collectors.toList());
    }

    private AccountInfoVO convertToVO(AccountInfo accountInfo) {
        if (accountInfo == null) {
            return null;
        }
        AccountInfoVO vo = new AccountInfoVO();
        BeanUtils.copyProperties(accountInfo, vo);
        return vo;
    }
}
